package com.jetinno.simple

import android.app.Dialog
import android.content.Context
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.Gravity
import android.view.View
import android.view.Window
import android.view.WindowManager
import androidx.annotation.ColorRes
import androidx.annotation.FloatRange
import androidx.annotation.StringRes
import androidx.core.content.ContextCompat
import com.jetinno.simple.utils.DialogPx
import com.jetinno.simple.utils.InputMethodUtil
import com.jetinno.simple.utils.ScreenUtil
import timber.log.Timber

/**
 * Created by zhangyuncai on 2021/7/29.
 */
abstract class SimpleDialog @JvmOverloads constructor(
    context: Context,
    themeResId: Int = 0
) : Dialog(context, themeResId) {

    val TAG = this::class.java.simpleName

    var hiddenSoft = false // dialog显示后，是否隐藏键盘

    var mSureCallback: ((Any?) -> Unit)? = null

    var mCancelCallback: ((Any?) -> Unit)? = null

    /**
     * 不适用SimpleDialog<T>的另一种方案
     */
    fun <T> setSureCallback(sureCallback: ((T?) -> Unit)?) {
        this.mSureCallback = sureCallback?.let { callback ->//callback就是sureCallback
            { value: Any? ->//let返回一个新增的函数体,对参数做一个安全的强转
                @Suppress("UNCHECKED_CAST")//屏蔽(Unchecked cast: Any? to T)警告
                callback(value as? T)
            }
        }
    }

    /**
     * 设置参数的同时,返回对象本身
     */
    fun <T> withSureCallback(sureCallback: ((T?) -> Unit)?): SimpleDialog {
        setSureCallback(sureCallback)
        return this
    }

    fun <T> setCancelCallback(cancelCallback: ((T?) -> Unit)?) {
        this.mCancelCallback = cancelCallback?.let { callback ->
            { value: Any? ->
                @Suppress("UNCHECKED_CAST")//屏蔽(Unchecked cast: Any? to T)警告
                callback(value as? T)
            }
        }
    }

    /**
     * 设置参数的同时,返回对象本身
     */
    fun <T> withCancelCallback(cancelCallback: ((T?) -> Unit)?): SimpleDialog {
        setCancelCallback(cancelCallback)
        return this
    }

    /**
     * mDatabinding = DataBindingUtil.inflate(
     *             layoutInflater,
     *             getLayoutId(),
     *             null,
     *             false
     *         )
     */
    protected open fun useDatabing(): View? {
        return null
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setWindowsStyle()
        val bindingView = useDatabing()
        if (bindingView == null) {
            setContentView(getLayoutId())
        } else {
            setContentView(bindingView)
        }
        initView()
        initEvent()
        setCanceledOnTouchOutside(false)
    }

    protected open fun setWindowsStyle() {
        // 去掉dialog的标题
        requestWindowFeature(Window.FEATURE_NO_TITLE)
        /* 设置与屏幕等宽 */
        val window = window
            // 隐藏底部导航栏
            window?.decorView?.systemUiVisibility =
                View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE
        window?.decorView?.setPadding(0, 0, 0, 0)
        val lp = window?.attributes
        if (hiddenSoft) {
            window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
        }
        lp?.width = getWidthStyle()
        lp?.height = getHeightStyle()
        lp?.gravity = getGravity()
        lp?.dimAmount = getDimAmout() // 透明底
        window?.attributes = lp
    }

    protected open fun getDimAmout(): Float {
        return 0.8f
    }

    protected abstract fun getLayoutId(): Int

    protected abstract fun initView()

    protected abstract fun initEvent()

    open fun onClick(view: View) {}

    protected fun addOnClick(vararg ids: Int) {
        for (id in ids) {
            findViewById<View>(id).setOnClickListener { v ->
                onClick(v)
            }
        }
    }

    protected fun getString(@StringRes res: Int): String {
        return context.resources.getString(res)
    }

    protected fun getColor(@ColorRes res: Int): Int {
        return ContextCompat.getColor(context, res)
    }

    protected fun closeKeyBoard() {
        InputMethodUtil.closeKeyBoard(context, window)
    }

    protected fun runOnUiThread(runnable: Runnable) {
        if (Looper.myLooper() == Looper.getMainLooper()) {
            runnable.run()
        } else {
            Handler(Looper.getMainLooper()).post(runnable)
        }
    }

    override fun show() {
        super.show()
        logLify("show")
    }

    override fun dismiss() {
        super.dismiss()
        logLify("dismiss")
    }

    @FloatRange(from = 0.0, to = 1.0)
    protected open fun getWidthPercent(): Double {
        return DialogPx.getWidthPercent()
    }

    protected open fun getWidthStyle(): Int {
        val widthPercent = getWidthPercent()
        return if (widthPercent > 0 && widthPercent < 1) {
            (ScreenUtil.getScreenWidth(context) * widthPercent).toInt()
        } else {
            WindowManager.LayoutParams.MATCH_PARENT
        }
    }

    @FloatRange(from = 0.0, to = 1.0)
    protected open fun getHeightPercent(): Double {
        return 0.0
    }

    protected open fun getHeightStyle(): Int {
        val heightPercent = getHeightPercent()
        return if (heightPercent > 0 && heightPercent < 1) {
            (ScreenUtil.getScreenHeight(context) * heightPercent).toInt()
        } else {
            WindowManager.LayoutParams.WRAP_CONTENT
        }
    }

    protected open fun getGravity(): Int {
        return Gravity.CENTER
    }

    /**
     * 打印生命周期
     */
    private fun logLify(state: String) {
        Timber.i(TAG, state)
    }
}
